/*
* ==============================================================================
*  Name        : game.cpp
*  Part of     : OpenC / OpenCOpenglEx
*  Interface   : 
*  Description : Contains the implementation of the CGame class.
*  Version     : 
*
*  Copyright (c) 2007 Nokia Corporation.
*  This material, including documentation and any related 
*  computer programs, is protected by copyright controlled by 
*  Nokia Corporation.
* ==============================================================================
*/


#include "game.h"
#include <e32base.h>
#ifdef __NANOGL__
#include <gl/gl.h>
#else
#ifdef SOFT_LINKAGE
#pragma softfp_linkage
#endif
#include <gles/gl.h> // for opengl es types 
#include "gpuDraw.h"
#ifdef SOFT_LINKAGE
#pragma no_softfp_linkage
#endif
#endif
#include <unistd.h>  // for usleep.
#include "r3000a.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "gpuPlugin.h"
//#include "padPlugin.h"

short int phone_button_map[16];
short int toggle_button_map[16];

extern bool iIsPause;
extern char IsoFile[1024];

#ifdef __cplusplus
}
#endif

static const int BUTTON_TRIANGLE = 0;
static const int BUTTON_CIRCLE = 1;
static const int BUTTON_CROSS = 2;
static const int BUTTON_SQUARE = 3;
static const int BUTTON_L2 = 4;
static const int BUTTON_R2 = 5;
static const int BUTTON_L1 = 6;
static const int BUTTON_R1 = 7;
static const int BUTTON_SELECT = 8;
static const int BUTTON_START = 11;
static const int BUTTON_UP = 12;
static const int BUTTON_RIGHT = 13;
static const int BUTTON_DOWN = 14;
static const int BUTTON_LEFT = 15;

// -----------------------------------------------------------------------------
// CGame::NewLC
// The factory function.
// -----------------------------------------------------------------------------
//

CGame* CGame::NewLC()
{
    CGame* self = new (ELeave) CGame;
    
    CleanupStack::PushL( self );
    
    self->ConstructL();

    return self;    
}

// -----------------------------------------------------------------------------
// CGame::CGame
// Constructor.
// -----------------------------------------------------------------------------
//
CGame::CGame()
      :iScreenWidth( 0 ),
       iScreenHeight( 0 ),
       iGameOver( EFalse ),
       iZPos( -100 ),
       iIsUpPressed( EFalse ),
       iIsDownPressed( EFalse ),
       iFrame( 0 )
{

}

// -----------------------------------------------------------------------------
// CGame::~CGame
// Destructor.
// -----------------------------------------------------------------------------
//
CGame::~CGame()
{
    Cleanup();
}

// -----------------------------------------------------------------------------
// CGame::Cleanup
// Perform any cleanup here.
// (does nothing)
// -----------------------------------------------------------------------------
//
void CGame::Cleanup()
{

}

// -----------------------------------------------------------------------------
// CGame::ConstructL
// Second phase contructor.
// (Does nothing)
// -----------------------------------------------------------------------------
//
void CGame::ConstructL()
{

}

// -----------------------------------------------------------------------------
// CGame::Initialize
// Initializes the opengl es state, based on the screen height and width.
// -----------------------------------------------------------------------------
//
void CGame::Initialize( TUint aScreenWidth, TUint aScreenHeight )
{
    iScreenWidth = aScreenWidth;
    iScreenHeight = aScreenHeight;
    iResX = iScreenWidth;
    iResY = iScreenHeight;
/*
    // Set the screen background color. 
    glClearColor( 0.f, 0.f, 0.f, 1.f );

    // Enable back face culling. 
    glEnable( GL_CULL_FACE  );

    // Initialize viewport and projection. 
    glViewport( 0, 0, iScreenWidth, iScreenHeight );
    glMatrixMode( GL_PROJECTION );

    // Calculate the view frustrum
    GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight);
    glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio,
                FRUSTUM_BOTTOM, FRUSTUM_TOP,
                FRUSTUM_NEAR, FRUSTUM_FAR );

    glMatrixMode( GL_MODELVIEW );

    // Enable vertex arrays. 
    glEnableClientState( GL_VERTEX_ARRAY );

    // Set array pointers. 
    glVertexPointer( 3, GL_BYTE, 0, vertices );

    // Enable color arrays. 
    glEnableClientState( GL_COLOR_ARRAY );

    // Set color pointers. 
    glColorPointer( 4, GL_UNSIGNED_BYTE, 0, colors );

    // Set the initial shading mode 
    glShadeModel( GL_FLAT ); 

    // Do not use perspective correction 
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );

    //GLWin.dpy 
  */  
}

// -----------------------------------------------------------------------------
// CGame::RenderFrame
// Renders a game frame using opengl es apis.
// It returns EFalse, if the game has ended.
// -----------------------------------------------------------------------------
//
TBool CGame::RenderFrame( TInt64 aMicrosSinceLastVisit )
{      
/*    if( iGameOver ) // If the game has ended, return EFalse to exit.
        return EFalse;
    
    // Ensure that the desired fps is maintained by sleeping 
    // for the rest of the time.   
    if( aMicrosSinceLastVisit < timeForOneFrame )
    {
        usleep( timeForOneFrame - aMicrosSinceLastVisit );    
    }
    
    // Clear the buffer.
    glClear( GL_COLOR_BUFFER_BIT );
        
    glLoadIdentity();
    
    // Move the Cube.
    glTranslatex( 0 , 0 , iZPos << 16 );
    
    // Rotate the cube.
    glRotatex( iFrame << 16, 1 << 16,    0   ,    0    );
    glRotatex( iFrame << 15,    0   , 1 << 16,    0    );
    glRotatex( iFrame << 14,    0   ,    0   , 1 << 16 );

    glScalef( 15.0f, 15.0f, 15.0f );
    
    glDrawElements( GL_TRIANGLES, 12 * 3, GL_UNSIGNED_BYTE, triangles );
    
    ++iFrame;
    
    // Move the cube if the up/down keys are pressed, but not released.
    // If the up/down keys are not released, then continuously move
    // cube.
    if( iIsUpPressed )
        --iZPos;
    
    if( iIsDownPressed )
        ++iZPos;
  */  
    return ETrue;
}

// -----------------------------------------------------------------------------
// CGame::HandleKeyEvent
// Handle a Key Event. This called by the Game Controller, when a key up/down
// event occurs.
// -----------------------------------------------------------------------------
//

void CheckButton(short int ind, TBool isUp)
{
	if (toggle_button_map[ind] == 0)
		phone_button_map[ind] = isUp ? 0 : 1;
	else
	if (isUp)
	    if (phone_button_map[ind] == 0)
	    	phone_button_map[ind] = 1;
	    else
	    	phone_button_map[ind] = 0;
	}

void CGame::HandleKeyEvent( TUint32 aKey, TBool aIsKeyUp )
{
   // Handle key events
        switch( aKey )
        {
        	case( EStdKeyLeftArrow ):
        	{
//        	phone_button_map[BUTTON_LEFT] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_LEFT, aIsKeyUp);
        	break;
        	}
        	case( EStdKeyRightArrow ):
        	{
//        	phone_button_map[BUTTON_RIGHT] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_RIGHT, aIsKeyUp);
        	break;
        	}
        	case( EStdKeyUpArrow ):
        	{
//        	phone_button_map[BUTTON_UP] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_UP, aIsKeyUp);
        	break;
        	}
        	case( EStdKeyDownArrow ):
        	{
//        	phone_button_map[BUTTON_DOWN] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_DOWN, aIsKeyUp);
        	break;
        	}
        	case( EStdKeyDevice0 ):
        	{
//        	phone_button_map[BUTTON_START] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_START, aIsKeyUp);
        	break;
        	}
        	case( '1' ):
    	    {
//        	phone_button_map[BUTTON_L1] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_L1, aIsKeyUp);
        	break;
        	}
        	case( '2' ):
    	    {
//        	phone_button_map[BUTTON_TRIANGLE] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_TRIANGLE, aIsKeyUp);
        	break;
        	}
        	case( '3' ):
    	    {
//        	phone_button_map[BUTTON_R1] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_R1, aIsKeyUp);
        	break;
        	}
        	case( '4' ):
    	    {
//        	phone_button_map[BUTTON_SQUARE] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_SQUARE, aIsKeyUp);
        	break;
        	}
        	case( '6' ):
    	    {
//        	phone_button_map[BUTTON_CIRCLE] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_CIRCLE, aIsKeyUp);
        	break;
        	}
        	case( '7' ):
    	    {
//        	phone_button_map[BUTTON_L2] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_L2, aIsKeyUp);
        	break;
        	}
        	case( '8' ):
    	    {
//        	phone_button_map[BUTTON_CROSS] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_CROSS, aIsKeyUp);
        	break;
        	}
        	case( '9' ):
    	    {
//        	phone_button_map[BUTTON_R2] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_R2, aIsKeyUp);
        	break;
        	}
        	case( '0' ):
    	    {
//        	phone_button_map[BUTTON_SELECT] = aIsKeyUp ? 0 : 1;
        	CheckButton(BUTTON_SELECT, aIsKeyUp);
        	break;
        	}
        	case( '*' ):
    	    {
    	    if (aIsKeyUp)
    	    {
				char FileName[256];
				sprintf(FileName,"%s%s",IsoFile,".sav");
				FILE *file = fopen((char*)FileName,"w");
				fclose(file);
				SaveState(FileName);
    	    }
    	    break;
        	}
        	case( EStdKeyHash ):
    	    {
    	    if (aIsKeyUp)
    	    	{
				char FileName[256];
				sprintf(FileName,"%s%s",IsoFile,".sav");
				if (LoadState(FileName) == -1)
					{
					SysMessage("ERROR LOADING STATE!");
					}
				else
					{
					SysMessage("STATE LOADED!");
					}
//				psxCpu->Execute();
    	    	}
        	break;
        	}
        	case( EStdKeyDevice1 ):
			{
    	    if (!aIsKeyUp)
			iIsPause = !iIsPause;
			break;
			}
            default:                
                break;
        }
}

// -----------------------------------------------------------------------------
// CGame::SetScreenSize
// Initialize the opengl viewport based on the screen width and height.
// This is called by the Game Controller when the screen size changes.
// -----------------------------------------------------------------------------
//
void CGame::SetScreenSize( TUint aScreenWidth, TUint aScreenHeight )
{    
    iScreenWidth = aScreenWidth;
    iScreenHeight = aScreenHeight;
    iResX = aScreenWidth;
    iResY = aScreenHeight;

    ResizeWindow();
//	GLinitialize();
    
    // Initialize the viewport and projection. 
/*    glViewport( 0, 0, iScreenWidth, iScreenHeight );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    
    // Calculate the view frustrum
    GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight);
#ifdef __NANOGL__
    glFrustum( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio,
                FRUSTUM_BOTTOM, FRUSTUM_TOP,
                FRUSTUM_NEAR, FRUSTUM_FAR );
#else
    glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio,
                FRUSTUM_BOTTOM, FRUSTUM_TOP,
                FRUSTUM_NEAR, FRUSTUM_FAR );
#endif
    
    glMatrixMode( GL_MODELVIEW );    
*/
}

// eof

